#ifndef __LOGGER_H__
#define __LOGGER_H__

#include <string>
#include <mutex>
#include <sys/time.h>
#include <ctime>

#define LOG_INI(path, name, level, size, output)    Logger::GetInstance().Init(path, name, level, size, output)
#define LOG_DBG(format, ...)                        Logger::GetInstance().Print(Logger::kDebug, __FILE__, __LINE__, __FUNCTION__, format,##__VA_ARGS__)
#define LOG_INF(format, ...)                        Logger::GetInstance().Print(Logger::kInfo, __FILE__, __LINE__, __FUNCTION__, format,##__VA_ARGS__)
#define LOG_WAR(format, ...)                        Logger::GetInstance().Print(Logger::kWarning, __FILE__, __LINE__, __FUNCTION__, format,##__VA_ARGS__)
#define LOG_ERR(format, ...)                        Logger::GetInstance().Print(Logger::kError, __FILE__, __LINE__, __FUNCTION__, format,##__VA_ARGS__)
#define LOG_FAT(format, ...)                        Logger::GetInstance().Print(Logger::kFatal, __FILE__, __LINE__, __FUNCTION__, format,##__VA_ARGS__)//;exit(0)
#define LOG_HEX(name, memory, size)                 Logger::GetInstance().Show(Logger::kDebug, __FILE__, __LINE__, __FUNCTION__, name, memory, size)

class Logger
{

public:

	enum Level{kDebug = 0, kInfo = 1, kWarning = 2, kError = 3, kFatal = 4};

	static Logger &GetInstance()
	{
		static Logger instance;
		return instance;
	}

	bool Init(const std::string &path, const std::string &name, Level level, size_t size, bool output);
	void Print(Level level, const std::string &file, unsigned int line, const std::string &function, const char *format, ...);
	void Show(Level level, const std::string &file, unsigned int line, const std::string &function, const std::string &name, const char *memory, size_t size);

private:

	Logger();
	Logger(const Logger &);
	Logger& operator=(const Logger&);

	std::string path_;
	std::string name_;
	Level level_;
	size_t size_;
	bool output_;
	std::mutex lock_;

};

#endif  //end of __LOGGER_H__